Narrow inner expression type when cast expression is used in strict/loose comparison#5665
Open
phpstan-bot wants to merge 1 commit into
Open
Narrow inner expression type when cast expression is used in strict/loose comparison#5665phpstan-bot wants to merge 1 commit into
phpstan-bot wants to merge 1 commit into
Conversation
…oose comparison - Add handling in `specifyTypesForConstantStringBinaryExpression` to propagate type narrowing from `(string)$x === ''` back to `$x`, removing `null`, `false`, and `''` from the inner expression's type - Add handling in `specifyTypesForConstantBinaryExpression` for `(int)` and `(float)` casts to remove `null` and `false` when comparing against zero/non-zero - Extend `resolveIdentical` normalization to also swap `Cast` expressions to the left side, matching the existing `FuncCall` normalization - Add inner expression narrowing in `resolveEqual` for the `== ''` handler when the expression is a `Cast\String_` - `(bool)` cast already works through existing `specifyTypesForConstantBinaryExpression` delegation to `specifyTypesInCondition`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a cast expression like
(string)$xis used in a comparison ((string)$x !== ''), PHPStan correctly narrows the type of the cast result but does not propagate the narrowing back to the inner expression$x. For example, with$x: string|null,(string)$x !== ''should narrow$xtonon-empty-string(removingnullsince(string)null === ''), but previously$xremainedstring|null.Changes
src/Analyser/TypeSpecifier.php:Cast\String_handling inspecifyTypesForConstantStringBinaryExpression: when(string)$xis compared to a constant string, propagates narrowing to$x. For empty string comparison, removesnull,false, and''from$x's type. For non-empty string comparisons in true context, removesnullandfalse.Cast\Int_andCast\Doublehandling inspecifyTypesForConstantBinaryExpression: when(int)$xor(float)$xis compared to a constant, removesnullandfalsefrom$x's type (only when comparison with zero value in false context, or non-zero value in true context).resolveIdenticalnormalization to also swapCastexpressions to the left side (matching existingFuncCallnormalization), ensuring reversed orderings like'' !== (string)$xwork correctly.resolveEqual's== ''handler forCast\String_expressions, fixing loose comparison narrowing.Analogous cases probed:
(bool)cast: already works correctly through existingspecifyTypesForConstantBinaryExpression→specifyTypesInConditionflow (verified with test)(int)cast: fixed, narrowing now propagates for(int)$x !== 0and(int)$x === 5patterns(float)cast: fixed, same pattern as int cast!=,==): fixed for string casts viaresolveEqualhandlerRoot cause
The
TypeSpecifiercreates type specifications (narrowing) for the expression used in a comparison, but when that expression is a cast like(string)$x, the narrowing was only applied to the cast result — not to the inner expression$x. The fix adds explicit handlers that detect cast expressions in comparisons and create additional type specifications for the inner expression based on the semantics of the cast (e.g.,(string)null === '',(int)null === 0).Test
tests/PHPStan/Analyser/nsrt/bug-8231.php: regression test for the reported bug with(string)cast comparisons including!==,===, reversed ordering, and various type combinations (string|null,int|null,string|false,bool|null)tests/PHPStan/Analyser/nsrt/bug-8231-analogous.php: tests for analogous cases with(int)cast,(float)cast,(bool)cast (already working), non-zero constant comparisons, reversed orderings, and loose string comparisonsFixes phpstan/phpstan#8231